﻿using System;
using System.Globalization;
using System.Xml;
using QQ2564874169.Core;
using QQ2564874169.Tencent.Weixin.Response;

namespace QQ2564874169.Tencent.Weixin.Notifys
{
    public class UnifiedorderNotify : WXXml
    {
        /// <summary>
        /// 微信分配的公众账号ID（企业号corpid即为此appId）
        /// </summary>
        public string appid { get; set; }
        /// <summary>
        /// 微信支付分配的商户号
        /// </summary>
        public string mch_id { get; set; }
        /// <summary>
        /// 微信支付分配的终端设备号
        /// </summary>
        public string device_info { get; set; }
        /// <summary>
        /// 随机字符串，不长于32位
        /// </summary>
        public string nonce_str { get; set; }
        public string sign { get; set; }
        public SignType sign_type { get; set; }
        public BusinessReturnCode result_code { get; set; }
        public UnifiedorderErrCode err_code { get; set; }
        /// <summary>
        /// 错误返回的信息描述
        /// </summary>
        public string err_code_des { get; set; }
        /// <summary>
        /// 用户在商户appid下的唯一标识
        /// </summary>
        public string openid { get; set; }
        /// <summary>
        /// 用户是否关注公众账号
        /// </summary>
        public bool is_subscribe { get; set; }
        public TradeType trade_type { get; set; }
        /// <summary>
        /// 银行类型，采用字符串类型的银行标识
        /// </summary>
        public string bank_type { get; set; }
        /// <summary>
        /// 订单总金额，单位为分
        /// </summary>
        public int total_fee { get; set; }
        /// <summary>
        /// 应结订单金额=订单金额-非充值代金券金额，应结订单金额小于等于订单金额。 
        /// </summary>
        public int settlement_total_fee { get; set; }
        /// <summary>
        /// 货币类型，符合ISO4217标准的三位字母代码，默认人民币：CNY
        /// </summary>
        public FeeType fee_type { get; set; }
        /// <summary>
        /// 现金支付金额订单现金支付金额
        /// </summary>
        public int cash_fee { get; set; }
        /// <summary>
        /// 货币类型，符合ISO4217标准的三位字母代码，默认人民币：CNY
        /// </summary>
        public FeeType cash_fee_type { get; set; }
        /// <summary>
        /// 代金券金额小于等于订单金额，订单金额-代金券金额=现金支付金额
        /// </summary>
        public int coupon_fee { get; set; }
        /// <summary>
        /// 代金券使用数量
        /// </summary>
        public int coupon_count { get; set; }
        /// <summary>
        /// 代金券详情
        /// </summary>
        public UnifiedorderCoupon[] coupons { get; private set; }
        /// <summary>
        /// 微信支付订单号
        /// </summary>
        public string transaction_id { get; set; }
        /// <summary>
        /// 商户系统内部订单号，要求32个字符内，只能是数字、大小写字母_-|*@ ，且在同一个商户号下唯一
        /// </summary>
        public string out_trade_no { get; set; }
        /// <summary>
        /// 商家数据包，原样返回
        /// </summary>
        public string attach { get; set; }
        /// <summary>
        /// 支付完成时间
        /// </summary>
        public DateTime time_end { get; set; }

        public UnifiedorderNotify(string appsecret, string outerXml) : base(outerXml)
        {
            if(appsecret == null)
                throw new ArgumentNullException(nameof(appsecret));
            if (outerXml == null)
                throw new ArgumentNullException(nameof(outerXml));

            if (result_code == BusinessReturnCode.SUCCESS && appsecret != "passsign")
            {
                var dict = Xml.ToDictionary(node => !node.Name.QQEquals(nameof(sign)));
                var xmlsign = WxSignHelper.PaySign(dict, appsecret, sign_type);
                if (sign.QQEquals(xmlsign) == false)
                {
                    throw new WXException($"返回内容验签失败。远程签名：{sign}。本地签名：{xmlsign}。返回内容：{outerXml}。");
                }
            }
            if (coupon_count > 0)
            {
                LoadCoupons();
            }
        }

        private void LoadCoupons()
        {
            coupons = new UnifiedorderCoupon[coupon_count];

            for (var i = 0; i < coupons.Length; i++)
            {
                coupons[i] = new UnifiedorderCoupon
                {
                    fee = Xml.SelectSingleNode("//coupon_fee_" + i).InnerText.ToInt().GetValueOrDefault(),
                    id = Xml.SelectSingleNode("//coupon_id_" + i).InnerText,
                    type = Xml.SelectSingleNode("//coupon_type_" + i).InnerText.ToEnum<CouponType>().GetValueOrDefault()
                };
            }
        }

        protected override object GetValue(Type propertyType, XmlNode xmlNode)
        {
            if (xmlNode.Name.QQEquals(nameof(is_subscribe)) && propertyType == typeof(bool))
            {
                return xmlNode.InnerText.QQEquals("Y");
            }
            if (propertyType == typeof(DateTime))
            {
                if (xmlNode.Name.QQEquals(nameof(time_end)))
                {
                    return DateTime.ParseExact(xmlNode.InnerText, "yyyyMMddHHmmss", DateTimeFormatInfo.CurrentInfo);
                }
            }
            return base.GetValue(propertyType, xmlNode);
        }
    }

    public class UnifiedorderCoupon
    {
        public CouponType type { get; set; }
        public string id { get; set; }
        public int fee { get; set; }
    }

    public enum CouponType
    {
        CASH,
        NO_CASH
    }
}
